﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Scommesse.Model.TipiRisultato;
using Scommesse.Utility;

namespace Scommesse.Model
{
    [Serializable]
    public class Evento : IEvento
    {
        private Dictionary<Tipologia, List<Quota>> _quote;
        private List<Risultato> _risultati;

        public Evento(string competitoreA, string competitoreB, DateTime dataOra, ICompetizione competizione)
        {
            if (competitoreA == null) throw new ArgumentNullException("competitoreA");
            if (competitoreB == null) throw new ArgumentNullException("competitoreB");
            if (dataOra == null)
                throw new ArgumentNullException("dataOra");
            Id = Guid.NewGuid();
            DataOra = dataOra.Subtract(new TimeSpan(0, 0, dataOra.Second));
            CompetitoreA = competitoreA;
            CompetitoreB = competitoreB;
            PunteggioA = 0;
            PunteggioB = 0;
            Stato = StatoEvento.Scommettibile;
            Competizione = competizione;
            
            // Aggiorna le quote
            RefreshQuote();
        }

        public Evento(Guid id, string competitoreA, string competitoreB, DateTime dataOra, StatoEvento stato, ICompetizione competizione) 
            : this(competitoreA, competitoreB, dataOra, competizione)
        {
            Id = id;
            Stato = stato;

            // Se l'evento scommettibile caricato da XML è iniziato, cambiagli lo stato
            if (dataOra <= DateTime.Now && stato.Equals(StatoEvento.Scommettibile))
                Stato = StatoEvento.InCorso;

            RefreshQuote();
        }

        public ICompetizione Competizione { get; private set; }

        public string CompetitoreA { get; private set; }

        public string CompetitoreB { get; private set; }

        public Guid Id { get; private set; }

        public int PunteggioA { get;  set; }

        public int PunteggioB { get; set; }

        public StatoEvento Stato { get; set; }

        public DateTime DataOra { get; private set; }

        public List<Risultato> Risultati
        {
            get { return _risultati; }
        }

        public Dictionary<Tipologia, List<Quota>> Quote
        {
            get { return _quote; }
            set { _quote = value; }
        }

        public void SetPunteggi(int punteggioA, int punteggioB)
        {
            PunteggioA = punteggioA;
            PunteggioB = punteggioB;
            _risultati = new List<Risultato>();
            foreach (KeyValuePair<Tipologia, Type> tipologia in Competizione.Categoria.Tipologie)
            {
                switch (tipologia.Key)
                {
                    case Tipologia.UXD:
                        if (punteggioA > punteggioB)
                            _risultati.Add(new Tipo1X2(Valori1X2.Uno));
                        else if (punteggioB > punteggioA)
                            _risultati.Add(new Tipo1X2(Valori1X2.Due));
                        else
                            _risultati.Add(new Tipo1X2(Valori1X2.X));
                        break;
                    case Tipologia.UD:
                        _risultati.Add(punteggioA > punteggioB
                                           ? new Tipo12(Valori12.Uno)
                                           : new Tipo12(Valori12.Due));
                        break;
                    case Tipologia.UO:
                        _risultati.Add(punteggioA + punteggioB >= 3
                                           ? new TipoUO(ValoriUO.Over)
                                           : new TipoUO(ValoriUO.Under));
                        break;
                    case Tipologia.GNG:
                        _risultati.Add((punteggioA > 0 && punteggioB > 0)
                                           ? new TipoGNG(ValoriGNG.Goal)
                                           : new TipoGNG(ValoriGNG.NoGoal));
                        break;
                }
            }
            Stato = StatoEvento.Terminato;
        }

        private void RefreshQuote()
        {
            Quote = QuoteRetriever.GetQuote(this);
        }
        
        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType())
                return false;
            var evento = (Evento) obj;
            return (CompetitoreA.ToLower().Equals(evento.CompetitoreA.ToLower()) && CompetitoreB.ToLower().Equals(evento.CompetitoreB.ToLower()) && DataOra.Equals(evento.DataOra) && Competizione.Equals(evento.Competizione));
        }

        public override int GetHashCode()
        {
            return GetType().GetHashCode();
        }

        public Quota GetQuotaByValore(String valore, Tipologia tipologia)
        {
            return Quote[tipologia].FirstOrDefault(q => StringValueAttribute.GetStringValue(q.Valore.GetValore()).Equals(valore));
        }
    }
}